// Fill out your copyright notice in the Description page of Project Settings.

#include "WorldEntity.h"
#include "WorldEntityReferencing.h"

WORLD_ENTITY_META_DEFINE(FWorldEntity, FWorldEntityPart);

FWorldEntity::FWorldEntity()
	: ID(this, -1)
	, Geom(this, "")
	, WorldId(this, -1)
	, RevisionStart(this, -1)
	, RevisionEnd(this, -1)
	, Referencer(this)
	, Referencee(this)
	, Class(this, "")
	, XmlClob(this, "")
	, Tags(this)
	, _state(EntityState::New)
	, _em(nullptr)
	, _dirty(false)
{}

FWorldEntity::FWorldEntity(const json& j)
	: ID(this, -1, j, "id")
	, Geom(this, "", j, "geom")
	, WorldId(this, -1, j, "idWorld")
	, RevisionStart(this, -1, j, "revisionStart")
	, RevisionEnd(this, -1, j, "revisionEnd")
	, Referencer(this, j, "idParent")
	, Referencee(this, j, "idReferences")
	, Class(this, "", j, "dataType")
	, XmlClob(this, "", j, "data")
	, Tags(this, j, "tags")
	, _state(EntityState::New)
	, _em(nullptr)
	, _dirty(false)
{
	auto xmlres = _xmldoc.load_string(
					XmlClob.Get().c_str(),
					pugi::parse_default | pugi::parse_comments);
	if (!xmlres)
	{
		throw XmlException(xmlres.description());
	}
	_xml = _xmldoc.child("object");
}

FWorldEntity::~FWorldEntity()
{}

void FWorldEntity::ToXml(pugi::xml_node& elem)
{}

json FWorldEntity::ToJson() const
{
	return {
		{"id", ID.Get()},
		{"geom", Geom.Get()},
		{"idWorld", WorldId.Get()},
		{"revisionStart", RevisionStart.Get()},
		{"revisionEnd", RevisionEnd.Get()},
		{"idParent", Referencer.Get()},
		{"idReferences", Referencee.Get()},
		{"dataType", Class.Get()},
		{"data", XmlClob.Get()},
		{"tags", Tags.Get()}
	};
}

void FWorldEntity::EntityChanged()
{
	if (_state == EntityState::Managed && _em)
	{
		const bool wasDirty = _dirty.exchange(true);
		if (!wasDirty)
		{
			_em->EntityChanged(As<FWorldEntity>());
		}
	}
}

void FWorldEntity::EntityFlushed()
{
	_dirty.exchange(false);
}

void FWorldEntity::ChangeTo(EntityState state, FWorldEntityManager* em)
{
	// Transition into the desired state.
	_state = state;
	_em = em;
}

bool FWorldEntity::Is(EntityState state)
{
	return _state == state;
}

bool FWorldEntity::IsManagedBy(FWorldEntityManager* em)
{
	return Is(EntityState::Managed) && _em == em;
}

void FWorldEntity::Resolve(FWorldEntityReferencing& referencing)
{
	Super::Resolve(referencing);
	referencing
		.Resolve(Referencer)
		.Resolve(Referencee);
}

void FWorldEntity::PropertyChanged()
{
	EntityChanged();
}
